home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / EnvMapping / CubeMap / cubemap.cpp next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  23.4 KB  |  730 lines

  1. //-----------------------------------------------------------------------------
  2. // File: CubeMap.cpp
  3. //
  4. // Desc: Example code showing how to do environment mapping
  5. //
  6. // Copyright (c) 1997-2001 Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include <tchar.h>
  10. #include <math.h>
  11. #include <stdio.h>
  12. #include <D3DX8.h>
  13. #include "D3DApp.h"
  14. #include "D3DFile.h"
  15. #include "D3DFont.h"
  16. #include "D3DUtil.h"
  17. #include "DXUtil.h"
  18.  
  19.  
  20. //-----------------------------------------------------------------------------
  21. // Name: g_szEffect
  22. // Desc: String containing effect used to render shiny teapot.  Two techniques
  23. //       are shown.. one which simply uses cubemaps, and a fallback which uses 
  24. //       a vertex shader to do a sphere-map lookup.
  25. //-----------------------------------------------------------------------------
  26.  
  27. const char g_szEffect[] = 
  28.  
  29.     "texture texCubeMap;\n"
  30.     "texture texSphereMap;\n"
  31.  
  32.     "matrix matWorld;\n"
  33.     "matrix matView;\n"
  34.     "matrix matProject;\n"
  35.     "matrix matWorldView;\n"
  36.  
  37.  
  38.     "technique Cube\n"
  39.     "{\n"
  40.         "pass P0\n"
  41.         "{\n"
  42.             // Vertex shate
  43.             "VertexShader = xyz | normal;\n"
  44.             "WorldTransform[0] = <matWorld>;\n"
  45.             "ViewTransform = <matView>;\n"
  46.             "ProjectionTransform = <matProject>;\n"
  47.  
  48.             // Pixel state
  49.             "Texture[0] = <texCubeMap>;\n"
  50.             
  51.             "MinFilter[0] = Linear;\n"
  52.             "MagFilter[0] = Linear;\n"
  53.  
  54.             "AddressU[0] = Clamp;\n"
  55.             "AddressV[0] = Clamp;\n"
  56.             "AddressW[0] = Clamp;\n"
  57.  
  58.             "ColorOp[0] = SelectArg1;\n"
  59.             "ColorArg1[0] = Texture;\n"
  60.  
  61.             "TexCoordIndex[0] = CameraSpaceReflectionVector;\n"
  62.             "TextureTransformFlags[0] = Count3;\n"
  63.         "}\n"
  64.     "}\n"
  65.  
  66.  
  67.     "technique Sphere\n"
  68.     "{\n"
  69.         "pass P0\n"
  70.         "{\n"
  71.  
  72.             // Vertex state
  73.             "VertexShader =\n"
  74.                 "decl\n"
  75.                 "{\n"
  76.                     "float v0[3];\n"  // position
  77.                     "float v1[3];\n"  // normal
  78.                 "}\n"
  79.                 "asm\n"
  80.                 "{\n"
  81.                     "vs.1.0\n"
  82.                     "def c64, 0.25f, 0.5f, 1.0f, -1.0f\n"
  83.         
  84.                     // r0: camera-space position
  85.                     // r1: camera-space normal
  86.                     // r2: camera-space vertex-eye vector
  87.                     // r3: camera-space reflection vector
  88.                     // r4: texture coordinates
  89.  
  90.                     // Transform position and normal into camera-space
  91.                     "m4x4 r0, v0, c0\n"
  92.                     "m3x3 r1, v1, c0\n"
  93.  
  94.                     // Compute normalized view vector
  95.                     "mov r2, -r0\n"
  96.                     "dp3 r3, r2, r2\n"
  97.                     "rsq r3, r3\n"
  98.                     "mul r2, r2, r3\n"
  99.  
  100.                     // Compute camera-space reflection vector
  101.                     "dp3 r3, r1, r2\n"
  102.                     "mul r1, r1, r3\n"
  103.                     "add r1, r1, r1\n"
  104.                     "add r3, r1, -r2\n"
  105.  
  106.                     // Compute sphere-map texture coords
  107.                     "mad r4.w, -r3.z, c64.y, c64.y\n"
  108.                     "rsq r4, r4\n"
  109.                     "mul r4, r3, r4\n"
  110.                     "mad r4, r4, c64.x, c64.y\n"
  111.  
  112.                     // Project position
  113.                     "m4x4 oPos, r0, c4\n"
  114.                     "mul oT0.xy, r4.xy, c64.zw\n"
  115.                     "mov oT0.zw, c64.z\n"
  116.                 "};\n"
  117.  
  118.             "VertexShaderConstant4[0] = <matWorldView>;\n"
  119.             "VertexShaderConstant4[4] = <matProject>;\n"
  120.  
  121.             // Pixel state
  122.             "Texture[0] = <texSphereMap>;\n"
  123.             "AddressU[0] = Wrap;\n"
  124.             "AddressV[0] = Wrap;\n"
  125.             "MinFilter[0] = Linear;\n"
  126.             "MagFilter[0] = Linear;\n"
  127.             "ColorOp[0] = SelectArg1;\n"
  128.             "ColorArg1[0] = Texture;\n"
  129.         "}\n"
  130.     "}\n";
  131.  
  132. const UINT g_cchEffect = sizeof(g_szEffect) - 1;
  133.  
  134.  
  135.  
  136.  
  137. //-----------------------------------------------------------------------------
  138. // Name: struct ENVMAPPEDVERTEX
  139. // Desc: D3D vertex type for environment-mapped objects
  140. //-----------------------------------------------------------------------------
  141. struct ENVMAPPEDVERTEX
  142. {
  143.     D3DXVECTOR3 p; // Position
  144.     D3DXVECTOR3 n; // Normal
  145. };
  146.  
  147. #define D3DFVF_ENVMAPVERTEX ( D3DFVF_XYZ | D3DFVF_NORMAL )
  148.  
  149. // CUBEMAP_RESOLUTION indicates how big to make the cubemap texture.  Larger
  150. // textures will generate a better-looking reflection.
  151. #define CUBEMAP_RESOLUTION 256
  152.  
  153.  
  154.  
  155. //-----------------------------------------------------------------------------
  156. // Name: class CMyD3DApplication
  157. // Desc: Application class. The base class (CD3DApplication) provides the 
  158. //       generic functionality needed in all Direct3D samples. CMyD3DApplication 
  159. //       adds functionality specific to this sample program.
  160. //-----------------------------------------------------------------------------
  161. class CMyD3DApplication : public CD3DApplication
  162. {
  163.     BOOL m_bCapture;
  164.  
  165.     D3DXMATRIX m_matProject;
  166.     D3DXMATRIX m_matView;
  167.     D3DXMATRIX m_matWorld;
  168.     D3DXMATRIX m_matAirplane;
  169.     D3DXMATRIX m_matTrackBall;
  170.  
  171.     CD3DFont* m_pFont;
  172.     CD3DMesh* m_pShinyTeapot;
  173.     CD3DMesh* m_pSkyBox;
  174.     CD3DMesh* m_pAirplane;
  175.  
  176.     ID3DXEffect* m_pEffect;
  177.     ID3DXRenderToEnvMap* m_pRenderToEnvMap;
  178.  
  179.     IDirect3DCubeTexture8* m_pCubeMap;
  180.     IDirect3DTexture8* m_pSphereMap;
  181.  
  182. protected:
  183.     HRESULT RenderSceneIntoEnvMap();
  184.     HRESULT RenderScene( CONST D3DXMATRIX* pView, CONST D3DXMATRIX* pProject, BOOL bRenderTeapot );
  185.  
  186.     HRESULT ConfirmDevice( D3DCAPS8*, DWORD, D3DFORMAT );
  187.     HRESULT OneTimeSceneInit();
  188.     HRESULT InitDeviceObjects();
  189.     HRESULT RestoreDeviceObjects();
  190.     HRESULT InvalidateDeviceObjects();
  191.     HRESULT DeleteDeviceObjects();
  192.     HRESULT Render();
  193.     HRESULT FrameMove();
  194.     HRESULT FinalCleanup();
  195.  
  196. public:
  197.     LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  198.  
  199.     CMyD3DApplication();
  200. };
  201.  
  202.  
  203.  
  204.  
  205. //-----------------------------------------------------------------------------
  206. // Name: WinMain()
  207. // Desc: Entry point to the program. Initializes everything, and goes into a
  208. //       message-processing loop. Idle time is used to render the scene.
  209. //-----------------------------------------------------------------------------
  210. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  211. {
  212.     CMyD3DApplication d3dApp;
  213.  
  214.     if( FAILED( d3dApp.Create( hInst ) ) )
  215.         return 0;
  216.  
  217.     return d3dApp.Run();
  218. }
  219.  
  220.  
  221.  
  222.  
  223. //-----------------------------------------------------------------------------
  224. // Name: CMyD3DApplication()
  225. // Desc: Application constructor. Sets attributes for the app.
  226. //-----------------------------------------------------------------------------
  227. CMyD3DApplication::CMyD3DApplication()
  228. {
  229.     m_strWindowTitle    = _T("CubeMap");
  230.     m_bUseDepthBuffer   = TRUE;
  231.     m_bCapture          = FALSE;
  232.  
  233.     m_pFont             = NULL;
  234.     m_pShinyTeapot      = NULL;
  235.     m_pSkyBox           = NULL;
  236.     m_pAirplane         = NULL;
  237.  
  238.     m_pEffect           = NULL;
  239.     m_pRenderToEnvMap   = NULL;
  240.  
  241.     m_pCubeMap          = NULL;
  242.     m_pSphereMap        = NULL;
  243. }
  244.  
  245.  
  246.  
  247.  
  248. //-----------------------------------------------------------------------------
  249. // Name: OneTimeSceneInit()
  250. // Desc: Called during initial app startup, this function performs all the
  251. //       permanent initialization.
  252. //-----------------------------------------------------------------------------
  253. HRESULT CMyD3DApplication::OneTimeSceneInit()
  254. {
  255.     D3DXMatrixIdentity( &m_matWorld );
  256.  
  257.     m_pFont        = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  258.     m_pShinyTeapot = new CD3DMesh();
  259.     m_pSkyBox      = new CD3DMesh();
  260.     m_pAirplane    = new CD3DMesh();
  261.  
  262.     if( !m_pFont || !m_pShinyTeapot || !m_pSkyBox || !m_pAirplane )
  263.         return E_OUTOFMEMORY;
  264.  
  265.     D3DXMatrixIdentity( &m_matTrackBall );
  266.     D3DXMatrixTranslation( &m_matView, 0.0f, 0.0f, 3.0f );
  267.  
  268.     return S_OK;
  269. }
  270.  
  271.  
  272.  
  273.  
  274. //-----------------------------------------------------------------------------
  275. // Name: FrameMove()
  276. // Desc: Called once per frame, the call is the entry point for animating
  277. //       the scene.
  278. //-----------------------------------------------------------------------------
  279. HRESULT CMyD3DApplication::FrameMove()
  280. {
  281.     // Animate file object
  282.     D3DXMATRIX  mat;
  283.     D3DXMatrixScaling( &m_matAirplane, 0.2f, 0.2f, 0.2f );
  284.     D3DXMatrixTranslation( &mat, 0.0f, 2.0f, 0.0f );
  285.     D3DXMatrixMultiply( &m_matAirplane, &m_matAirplane, &mat );
  286.     D3DXMatrixRotationX( &mat, -2.9f * m_fTime );
  287.     D3DXMatrixMultiply( &m_matAirplane, &m_matAirplane, &mat );
  288.     D3DXMatrixRotationY( &mat, 1.055f * m_fTime );
  289.     D3DXMatrixMultiply( &m_matAirplane, &m_matAirplane, &mat );
  290.  
  291.     // When the window has focus, let the mouse adjust the camera view
  292.     if( m_bCapture )
  293.     {
  294.         D3DXMATRIX matCursor;
  295.         D3DXQUATERNION qCursor = D3DUtil_GetRotationFromCursor( m_hWnd );
  296.         D3DXMatrixRotationQuaternion( &matCursor, &qCursor );
  297.         D3DXMatrixMultiply( &m_matView, &m_matTrackBall, &matCursor );
  298.  
  299.         D3DXMATRIX matTrans;
  300.         D3DXMatrixTranslation( &matTrans, 0.0f, 0.0f, 3.0f );
  301.         D3DXMatrixMultiply( &m_matView, &m_matView, &matTrans );
  302.     }
  303.  
  304.  
  305.     // Render the scene into the surfaces of the cubemap
  306.     if( FAILED( RenderSceneIntoEnvMap() ) )
  307.         return E_FAIL;
  308.  
  309.     return S_OK;
  310. }
  311.  
  312.  
  313.  
  314.  
  315. //-----------------------------------------------------------------------------
  316. // Name: RenderSceneIntoEnvMap()
  317. // Desc: Renders the scene to each of the 6 faces of the cube map
  318. //-----------------------------------------------------------------------------
  319. HRESULT CMyD3DApplication::RenderSceneIntoEnvMap()
  320. {
  321.     HRESULT hr;
  322.  
  323.     // Set the projection matrix for a field of view of 90 degrees
  324.     D3DXMATRIX matProj;
  325.     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI * 0.5f, 1.0f, 0.5f, 1000.0f );
  326.  
  327.  
  328.     // Get the current view matrix, to concat it with the cubemap view vectors
  329.     D3DXMATRIX matViewDir( m_matView );
  330.     matViewDir._41 = 0.0f; matViewDir._42 = 0.0f; matViewDir._43 = 0.0f;
  331.  
  332.  
  333.  
  334.     // Render the six cube faces into the environment map
  335.     if( m_pCubeMap )
  336.         hr = m_pRenderToEnvMap->BeginCube( m_pCubeMap );
  337.     else
  338.         hr = m_pRenderToEnvMap->BeginSphere( m_pSphereMap );
  339.  
  340.     if(FAILED(hr))
  341.         return hr;
  342.  
  343.     for( UINT i = 0; i < 6; i++ )
  344.     {
  345.         m_pRenderToEnvMap->Face( (D3DCUBEMAP_FACES) i );
  346.  
  347.         // Set the view transform for this cubemap surface
  348.         D3DXMATRIX matView;
  349.         matView = D3DUtil_GetCubeMapViewMatrix( (D3DCUBEMAP_FACES) i );
  350.         D3DXMatrixMultiply( &matView, &matViewDir, &matView );
  351.  
  352.         // Render the scene (except for the teapot)
  353.         RenderScene( &matView, &matProj, FALSE );
  354.     }
  355.  
  356.     m_pRenderToEnvMap->End();
  357.     return S_OK;
  358. }
  359.  
  360.  
  361.  
  362.  
  363. //-----------------------------------------------------------------------------
  364. // Name: RenderScene()
  365. // Desc: Renders all visual elements in the scene. This is called by the main
  366. //       Render() function, and also by the RenderIntoCubeMap() function.
  367. //-----------------------------------------------------------------------------
  368. HRESULT CMyD3DApplication::RenderScene( CONST D3DXMATRIX *pView, CONST D3DXMATRIX *pProject, 
  369.                                         BOOL bRenderTeapot )
  370. {
  371.     // Render the Skybox
  372.     {
  373.         D3DXMATRIX matWorld;
  374.         D3DXMatrixScaling( &matWorld, 10.0f, 10.0f, 10.0f );
  375.  
  376.         D3DXMATRIX matView(*pView);
  377.         matView._41 = matView._42 = matView._43 = 0.0f;
  378.  
  379.         m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  380.         m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  381.         m_pd3dDevice->SetTransform( D3DTS_PROJECTION, pProject );
  382.  
  383.         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  384.         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1 );
  385.         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  386.         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  387.         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU,  D3DTADDRESS_MIRROR );
  388.         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV,  D3DTADDRESS_MIRROR );
  389.  
  390.         // Always pass Z-test, so we can avoid clearing color and depth buffers
  391.         m_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_ALWAYS );
  392.         m_pSkyBox->Render( m_pd3dDevice );
  393.         m_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );
  394.     }
  395.  
  396.  
  397.     // Render the Airplane
  398.     {
  399.         m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matAirplane );
  400.         m_pd3dDevice->SetTransform( D3DTS_VIEW, pView );
  401.         m_pd3dDevice->SetTransform( D3DTS_PROJECTION, pProject );
  402.  
  403.         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  404.         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1 );
  405.         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  406.         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  407.         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU,  D3DTADDRESS_WRAP );
  408.         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV,  D3DTADDRESS_WRAP );
  409.  
  410.         m_pAirplane->Render( m_pd3dDevice );
  411.  
  412.         m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matWorld);
  413.     }
  414.  
  415.  
  416.     // Render the environment-mapped ShinyTeapot
  417.     if( bRenderTeapot )
  418.     {
  419.         // Set transform state
  420.         if( m_pCubeMap )
  421.         {
  422.             m_pEffect->SetMatrix( "matWorld", &m_matWorld );
  423.             m_pEffect->SetMatrix( "matView", (D3DXMATRIX*) pView );
  424.         }
  425.         else
  426.         {
  427.             D3DXMATRIX matWorldView;
  428.             D3DXMatrixMultiply( &matWorldView, &m_matWorld, pView );
  429.             m_pEffect->SetMatrix( "matWorldView", &matWorldView );
  430.         }
  431.  
  432.         m_pEffect->SetMatrix( "matProject", (D3DXMATRIX*) pProject );
  433.  
  434.  
  435.         // Draw teapot
  436.         LPDIRECT3DVERTEXBUFFER8 pVB;
  437.         LPDIRECT3DINDEXBUFFER8 pIB;
  438.  
  439.         m_pShinyTeapot->m_pLocalMesh->GetVertexBuffer(&pVB);
  440.         m_pShinyTeapot->m_pLocalMesh->GetIndexBuffer(&pIB);
  441.  
  442.         m_pd3dDevice->SetStreamSource(0, pVB, sizeof(ENVMAPPEDVERTEX));
  443.         m_pd3dDevice->SetIndices(pIB, 0);
  444.  
  445.         UINT uPasses;
  446.         m_pEffect->Begin( &uPasses, 0 );
  447.  
  448.         for( UINT iPass = 0; iPass < uPasses; iPass++ )
  449.         {
  450.             m_pEffect->Pass( iPass );
  451.  
  452.             m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
  453.                 0, m_pShinyTeapot->m_pLocalMesh->GetNumVertices(),
  454.                 0, m_pShinyTeapot->m_pLocalMesh->GetNumFaces());
  455.  
  456.         }
  457.  
  458.         m_pEffect->End();
  459.  
  460.         SAFE_RELEASE(pVB);
  461.         SAFE_RELEASE(pIB);
  462.     }
  463.  
  464.     return S_OK;
  465. }
  466.  
  467.  
  468.  
  469.  
  470. //-----------------------------------------------------------------------------
  471. // Name: Render()
  472. // Desc: Called once per frame, the call is the entry point for 3d
  473. //       rendering. This function sets up render states, clears the
  474. //       viewport, and renders the scene.
  475. //-----------------------------------------------------------------------------
  476. HRESULT CMyD3DApplication::Render()
  477. {
  478.     // Begin the scene
  479.     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
  480.     {
  481.         // Render the scene, including the teapot
  482.         RenderScene( &m_matView, &m_matProject, TRUE );
  483.  
  484.         // Output statistics
  485.         m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  486.         m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  487.  
  488.         // End the scene.
  489.         m_pd3dDevice->EndScene();
  490.     }
  491.  
  492.     return S_OK;
  493. }
  494.  
  495.  
  496.  
  497.  
  498. //-----------------------------------------------------------------------------
  499. // Name: InitDeviceObjects()
  500. // Desc: Initialize scene objects.
  501. //-----------------------------------------------------------------------------
  502. HRESULT CMyD3DApplication::InitDeviceObjects()
  503. {
  504.     // Load the file objects
  505.     if( FAILED( m_pShinyTeapot->Create( m_pd3dDevice, _T("teapot.x") ) ) )
  506.         return D3DAPPERR_MEDIANOTFOUND;
  507.     if( FAILED( m_pSkyBox->Create( m_pd3dDevice, _T("lobby_skybox.x") ) ) )
  508.         return D3DAPPERR_MEDIANOTFOUND;
  509.     if( FAILED( m_pAirplane->Create( m_pd3dDevice, _T("airplane 2.x") ) ) )
  510.         return D3DAPPERR_MEDIANOTFOUND;
  511.  
  512.     // Set mesh properties
  513.     m_pAirplane->SetFVF( m_pd3dDevice, D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1 );
  514.     m_pShinyTeapot->SetFVF( m_pd3dDevice, D3DFVF_ENVMAPVERTEX );
  515.  
  516.     // Restore the device-dependent objects
  517.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  518.  
  519.     // Create Effect object
  520.     if( FAILED( D3DXCreateEffect( m_pd3dDevice, g_szEffect, g_cchEffect, &m_pEffect, NULL ) ) )
  521.         return E_FAIL;
  522.  
  523.     return S_OK;
  524. }
  525.  
  526.  
  527.  
  528.  
  529. //-----------------------------------------------------------------------------
  530. // Name: RestoreDeviceObjects()
  531. // Desc: Restore device-memory objects and state after a device is created or
  532. //       resized.
  533. //-----------------------------------------------------------------------------
  534. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  535. {
  536.     // InitDeviceObjects for file objects (build textures and vertex buffers)
  537.     m_pShinyTeapot->RestoreDeviceObjects( m_pd3dDevice );
  538.     m_pSkyBox->RestoreDeviceObjects( m_pd3dDevice );
  539.     m_pAirplane->RestoreDeviceObjects( m_pd3dDevice );
  540.     m_pFont->RestoreDeviceObjects();
  541.     m_pEffect->OnResetDevice();
  542.  
  543.  
  544.  
  545.     // Create RenderToEnvMap object
  546.     if( FAILED( D3DXCreateRenderToEnvMap( m_pd3dDevice, CUBEMAP_RESOLUTION, 
  547.         m_d3dsdBackBuffer.Format, TRUE, D3DFMT_D16, &m_pRenderToEnvMap ) ) )
  548.     {
  549.         return E_FAIL;
  550.     }
  551.  
  552.  
  553.     // Create the cubemap, with a format that matches the backbuffer
  554.     if( m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP )
  555.     {
  556.         if( FAILED( D3DXCreateCubeTexture( m_pd3dDevice, CUBEMAP_RESOLUTION, 1,
  557.             D3DUSAGE_RENDERTARGET, m_d3dsdBackBuffer.Format, D3DPOOL_DEFAULT, &m_pCubeMap ) ) )
  558.         {
  559.             if( FAILED( D3DXCreateCubeTexture( m_pd3dDevice, CUBEMAP_RESOLUTION, 1,
  560.                 0, m_d3dsdBackBuffer.Format, D3DPOOL_DEFAULT, &m_pCubeMap ) ) )
  561.             {
  562.                 m_pCubeMap = NULL;
  563.             }
  564.         }
  565.     }
  566.  
  567.  
  568.     // Create the spheremap, with a format that matches the backbuffer
  569.     if( !m_pCubeMap )
  570.     {
  571.         if( FAILED( D3DXCreateTexture( m_pd3dDevice, CUBEMAP_RESOLUTION, CUBEMAP_RESOLUTION, 
  572.             1, D3DUSAGE_RENDERTARGET, m_d3dsdBackBuffer.Format, D3DPOOL_DEFAULT, &m_pSphereMap ) ) )
  573.         {
  574.             if( FAILED( D3DXCreateTexture( m_pd3dDevice, CUBEMAP_RESOLUTION, CUBEMAP_RESOLUTION, 
  575.                 1, 0, m_d3dsdBackBuffer.Format, D3DPOOL_DEFAULT, &m_pSphereMap ) ) )
  576.             {
  577.                 return E_FAIL;
  578.             }
  579.         }
  580.     }
  581.  
  582.  
  583.     // Initialize effect
  584.     m_pEffect->SetTexture( "texCubeMap", m_pCubeMap );
  585.     m_pEffect->SetTexture( "texSphereMap", m_pSphereMap );
  586.  
  587.     if( m_pCubeMap )
  588.     {
  589.         m_pEffect->SetTechnique( "Cube" );
  590.         SetWindowText( m_hWnd, _T("CubeMap: Environment cube-mapping") );
  591.     }
  592.     else
  593.     {
  594.         m_pEffect->SetTechnique( "Sphere" );
  595.         SetWindowText( m_hWnd, _T("CubeMap: Environment cube-mapping (using dynamic spheremap)") );
  596.     }
  597.  
  598.  
  599.     // Set the transform matrices
  600.     FLOAT fAspect = (FLOAT) m_d3dsdBackBuffer.Width / (FLOAT) m_d3dsdBackBuffer.Height;
  601.     D3DXMatrixPerspectiveFovLH( &m_matProject, D3DX_PI * 0.4f, fAspect, 0.5f, 100.0f );
  602.  
  603.  
  604.     return S_OK;
  605. }
  606.  
  607.  
  608.  
  609.  
  610. //-----------------------------------------------------------------------------
  611. // Name: InvalidateDeviceObjects()
  612. // Desc: Called when the device-dependent objects are about to be lost.
  613. //-----------------------------------------------------------------------------
  614. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  615. {
  616.     m_pShinyTeapot->InvalidateDeviceObjects();
  617.     m_pSkyBox->InvalidateDeviceObjects();
  618.     m_pAirplane->InvalidateDeviceObjects();
  619.     m_pFont->InvalidateDeviceObjects();
  620.  
  621.     if(m_pEffect)
  622.         m_pEffect->OnLostDevice();
  623.  
  624.     SAFE_RELEASE( m_pRenderToEnvMap );
  625.     SAFE_RELEASE( m_pCubeMap );
  626.     SAFE_RELEASE( m_pSphereMap );
  627.  
  628.     return S_OK;
  629. }
  630.  
  631.  
  632.  
  633.  
  634. //-----------------------------------------------------------------------------
  635. // Name: DeleteDeviceObjects()
  636. // Desc: Called when the app is exiting, or the device is being changed,
  637. //       this function deletes any device dependent objects.
  638. //-----------------------------------------------------------------------------
  639. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  640. {
  641.     m_pFont->DeleteDeviceObjects();
  642.     m_pShinyTeapot->Destroy();
  643.     m_pSkyBox->Destroy();
  644.     m_pAirplane->Destroy();
  645.  
  646.     SAFE_RELEASE( m_pEffect );
  647.  
  648.     return S_OK;
  649. }
  650.  
  651.  
  652.  
  653.  
  654. //-----------------------------------------------------------------------------
  655. // Name: FinalCleanup()
  656. // Desc: Called before the app exits, this function gives the app the chance
  657. //       to cleanup after itself.
  658. //-----------------------------------------------------------------------------
  659. HRESULT CMyD3DApplication::FinalCleanup()
  660. {
  661.     SAFE_DELETE( m_pFont );
  662.     SAFE_DELETE( m_pShinyTeapot );
  663.     SAFE_DELETE( m_pSkyBox );
  664.     SAFE_DELETE( m_pAirplane );
  665.  
  666.     return S_OK;
  667. }
  668.  
  669.  
  670.  
  671.  
  672. //-----------------------------------------------------------------------------
  673. // Name: ConfirmDevice()
  674. // Desc: Called during device intialization, this code checks the device
  675. //       for some minimum set of capabilities
  676. //-----------------------------------------------------------------------------
  677. HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
  678.                                           D3DFORMAT Format )
  679. {
  680.     if( dwBehavior & D3DCREATE_PUREDEVICE )
  681.         return E_FAIL;
  682.  
  683.     if( !(pCaps->TextureCaps & D3DPTEXTURECAPS_CUBEMAP) &&
  684.         !(dwBehavior & D3DCREATE_SOFTWARE_VERTEXPROCESSING) &&
  685.         !(pCaps->VertexShaderVersion >= D3DVS_VERSION(1, 0)) )
  686.     {
  687.         return E_FAIL;
  688.     }
  689.  
  690.     return S_OK;
  691. }
  692.  
  693.  
  694. //-----------------------------------------------------------------------------
  695. // Name: MsgProc()
  696. // Desc: Message proc function to handle key and menu input
  697. //-----------------------------------------------------------------------------
  698. LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
  699.                                     LPARAM lParam )
  700. {
  701.     // Capture mouse when clicked
  702.     if( WM_LBUTTONDOWN == uMsg )
  703.     {
  704.         D3DXMATRIX matCursor;
  705.         D3DXQUATERNION qCursor = D3DUtil_GetRotationFromCursor( m_hWnd );
  706.         D3DXMatrixRotationQuaternion( &matCursor, &qCursor );
  707.         D3DXMatrixTranspose( &matCursor, &matCursor );
  708.         D3DXMatrixMultiply( &m_matTrackBall, &m_matTrackBall, &matCursor );
  709.  
  710.         SetCapture( m_hWnd );
  711.         m_bCapture = TRUE;
  712.         return 0;
  713.     }
  714.  
  715.     if( WM_LBUTTONUP == uMsg )
  716.     {
  717.         D3DXMATRIX matCursor;
  718.         D3DXQUATERNION qCursor = D3DUtil_GetRotationFromCursor( m_hWnd );
  719.         D3DXMatrixRotationQuaternion( &matCursor, &qCursor );
  720.         D3DXMatrixMultiply( &m_matTrackBall, &m_matTrackBall, &matCursor );
  721.  
  722.         ReleaseCapture();
  723.         m_bCapture = FALSE;
  724.         return 0;
  725.     }
  726.  
  727.     // Pass remaining messages to default handler
  728.     return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam );
  729. }
  730.